package objects;

import graphic.Color;
import java.util.LinkedList;
import java.util.List;
import klient.Bridge;
import klient.Klient;
import org.lwjgl.util.vector.Vector3f;

/**
 *  
 * @author Bartek & Marcin
 * 
 * @description Defines any type of a Tower. It can be Tower with movable or static canon
 */
public class Tower {
    public OBJ_Loader.Object Main;
    public OBJ_Loader.Object Canon;
    public Boolean builded = false;
    public SRect rect = new SRect();
    public int type;
    public float size=4f;
    public int cost=100;
    public float power=3f;
    public int speed=500;
    public float mSize=10.4f;
    public Color buildedC = new Color(1.0f,0.0f,0.0f,1f);
    public Color badPlaceC = new Color(1.0f,0.0f,0.0f,0.5f);
    public Color goodPlaceC = new Color(0.0f,1.0f,0.0f,0.5f);
    public Boolean hasAim = false;
    private MobInfo Aim = null;
    public float angle_mask = 0;
    public float range = 1f;
    public int angle_speed = 20;
    public TowerCollisionArea actCollision, nextCollision;
    private int TimeID;
    private int AttackID;
    private Boolean dirOk = false;
    
    public void move(float x,float y, float z){
        Main.move(x, y, z);
        if(Canon!=null) Canon.move(x, y, z);
    }
    public void setRot(float rot){
        Main.setRotateY(rot);
        if(Canon!=null) Canon.setRotateY(rot);
    }
    public void setTowerColor(Color col){
         Main.setColor(col.R, col.G, col.B, col.A);
        if(Canon!=null){Canon.setColor(col.R, col.G, col.B, col.A);}
    }
    private void init(int type, float x, float y, float z){
        this.type= type;
        switch(type){
           case 1:
                Main = new OBJ_Loader.Object("obj/tower1.obj",x,y,z);
                Canon = new OBJ_Loader.Object("obj/tower1canon.obj",x,y,z);
                size*=0.5f;
                Main.setScale(0.5f);
                Canon.setScale(0.5f);
                power =15f;
                angle_mask = 270;
                speed=500;
                this.range = 10.0f;
                cost=30;
                break;
        }
        this.setTowerColor(badPlaceC);
        rect.set(x-size, y+size, z-size, z+size);
        TimeID = TimeManager.register(100);
        AttackID = TimeManager.register(speed);
    }
    public Tower(int type){
        this.init(type,0.0f,0.0f,0.0f);
    }
    public Tower(int type, float x, float y, float z){
       this.init(type, x, y, z);
    }
    public Boolean checkAim(MobInfo toCheck){
        if(Aim == null ) {return false;}
        if(Aim.equals(toCheck)){ return true;}
        return false;
    }
    public void build(){
        this.builded = true;
         this.setTowerColor(buildedC);
    }
    public SRect getRect(){
        return rect;
    }
    public void setAim(MobInfo mob){
        Aim = mob;
        hasAim = true;
    }
    public void setAim(MobInfo mob, TowerCollisionArea now, TowerCollisionArea next){
        Aim = mob;
        this.actCollision = now;
        this.nextCollision = next;
        hasAim = true;
    }
    public void removeAim(){      
        Aim = null;
        hasAim = false;
    }
    public void draw(int player){
        Main.draw();
        if(Canon!=null){ 
            if(hasAim&&TimeManager.check(TimeID)){
                this.aim();
                if(!ActionEngine.isInSquare(actCollision, Aim.M.pos)){
                   if(!ActionEngine.isInSquare(nextCollision, Aim.M.pos)){
                       this.removeAim();
                    }
                }
            }
            
            Canon.draw();
            
        }
        if( hasAim && TimeManager.check(AttackID)){
                if(dirOk){
                    //SHOOT!
                    this.shoot();
                }
               if(player == (Bridge.isMulti?Klient.uS.IDinGame:0)){ Aim.attack(power); }
        }
    }
    public void registerYourself(List<List<TowerCollisionArea>> checkReg, List<Vector3f> checkSet){
        for(int i=1;i<checkSet.size();i++){
            float Ac, Bc, Cc,Apc,Bpc,Cpc,Zb,Za,Xb,Xa;
            Xa = checkSet.get(i-1).x;
            Za = checkSet.get(i-1).z;
            Xb = checkSet.get(i).x;
            Zb = checkSet.get(i).z;
            
            float Vcx = Xb-Xa;
            float Vcz = Zb-Za;
            Ac = (-1)*(Vcz);
            Bc = Vcx;
            Cc = ((-1)*Za*Vcx) + Xa*(Vcz);
            
            float odl = (Math.abs(Ac*this.Main.getPos().x + Bc*this.Main.getPos().z + Cc))/(float)Math.sqrt((float)(Ac*Ac) + (float)(Bc*Bc)); 
            if(odl > this.range){
                continue;
            }
             float lenC = (float)Math.sqrt(Vcx*Vcx + Vcz*Vcz);
            float lenCpart = (float)Math.sqrt(this.range * this.range - odl*odl);
            float tmp = (lenCpart/lenC);
            float Vpx = Vcx*tmp;
            float Vpz = Vcz*tmp;
            Apc = (-1)*Bc;
            Bpc = Ac;
            Cpc = (-1)*Apc*this.Main.getPos().x - Bpc*this.Main.getPos().z;
            
            float Xs,Zs;
            Xs = (Bc*Cpc - Bpc*Cc)/(Ac*Bpc - Bc*Apc);
            Zs = ((-1)*(Ac*Xs + Cc))/Bc;
 
            double Xpb,Zpb,Xpe,Zpe;
            Xpb = Xs-Vpx;
            Zpb = Zs-Vpz;
            Xpe = Xs+Vpx;
            Zpe = Zs+Vpz;
            if(((Vcx > 0 && (Xpb > Xb || Xpb < Xa) )||(Vcx < 0 && (Xpb < Xb || Xpb > Xa) ))&&((Vcx > 0 && 
                    (Xpe > Xb || Xpe < Xa) )||(Vcx < 0 && (Xpe < Xb || Xpe > Xa) ))){
                continue;
            }
            if(((Vcz > 0 && (Zpb > Zb || Zpb < Za) )||(Vcz < 0 && (Zpb < Zb || Zpb > Za) ))&&((Vcz > 0 && 
                    (Zpe > Zb || Zpe < Za) )||(Vcz < 0 && (Zpe < Zb || Zpe > Za) ))){
                continue;
            }
            checkReg.get(i).add(new TowerCollisionArea(this,new Vector3f((float)Xpb,checkSet.get(i).y,(float)Zpb),new Vector3f((float)Xpe,checkSet.get(i).y,(float)Zpe)));
        } 
    }
    private void aim(){
        float dx =  Canon.getPos().x - Aim.M.pos.x;
        float dz =  Canon.getPos().z - Aim.M.pos.z;
        float dir = (float)(Math.atan(Math.abs(dz)/Math.abs(dx))*180/(Math.PI)); 
        if(dx>=0){
           if(dz>=0){
               dir *= -1;
                dir+=180;
           } else{
                dir+=180;
           }
        }
        else{
            if(dz>=0){   
           }else{
               dir *= -1;
               dir+=360;
          }
        }
        dir-=angle_mask;
        if(dir>360) dir-=360;
        else if(dir<0) dir+=360;
        this.dirOk = false;
        float sign = 1;
        if(Canon.getRot().y > 360){
            Canon.getRot().y -= 360;
        }
        else{
            if(Canon.getRot().y < 0){
            Canon.getRot().y += 360;
            }
        }
        if(dir < Canon.getRot().y - angle_speed){
        }
        else{
            if(dir > Canon.getRot().y + angle_speed){
           } 
            else{
                 Canon.getRot().y = dir;
                 this.dirOk = true;
            }
        }
        if(!dirOk){
            float dif = dir-Canon.getRot().y;
            if(dif > 180 || dif< 0){
                if(dif < -180){ sign = 1; }
                else {sign = -1;}
            }
            
            Canon.getRot().y+= sign*angle_speed;
        }
    }
    private void shoot(){
        
    }
}
